home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / bin / restricted-manager < prev    next >
Encoding:
Text File  |  2007-04-12  |  14.1 KB  |  405 lines

  1. #!/usr/bin/python
  2. # -*- coding: UTF-8 -*-
  3.  
  4. # This program is free software; you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation; either version 2 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License along
  15. # with this program; if not, write to the Free Software Foundation, Inc.,
  16. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17.  
  18. """Restricted Modules Manager.
  19.  
  20. Usage:
  21.   --update          Update the restricted modules list
  22.   --check           Check for newly used restricted modules
  23.   --enable MODULE   Enable the named module
  24.   --disable MODULE  Disable the named module
  25.   --check-composite Check if there is a graphics driver available that supports
  26.                     composite and offer to enable it
  27.  
  28. Without arguments, immediately loads the restricted modules manager
  29. window.
  30. """
  31.  
  32. __copyright__ = "Copyright ┬⌐ 2007 Canonical Ltd."
  33. __author__    = "Scott James Remnant <scott@ubuntu.com>"
  34.  
  35.  
  36. import os
  37. import sys
  38. import gettext
  39. from optparse import OptionParser
  40.  
  41. import pygtk
  42. pygtk.require("2.0")
  43.  
  44. import gobject
  45. import gtk
  46. import gtk.glade
  47. import pynotify
  48.  
  49. import RestrictedManager
  50. from RestrictedManager.core import *
  51.  
  52. from gettext import gettext as _
  53.  
  54. class ManagerWindow(object):
  55.     def __init__(self, xml, handlers):
  56.         self.xml = xml
  57.  
  58.         gtk.window_set_default_icon_name("restricted-manager")
  59.         self.dialog = self.xml.get_widget("dialog_manager")
  60.         self.dialog.connect("delete_event", self.on_dialog_delete_event)
  61.  
  62.         self.treeview = self.xml.get_widget("treeview_drivers")
  63.         self.treeview.get_selection().set_mode(gtk.SELECTION_NONE)
  64.  
  65.         text_renderer = gtk.CellRendererText()
  66.         col1 = gtk.TreeViewColumn(_("Driver"))
  67.         col1.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
  68.         col1.set_expand(True)
  69.         col1.pack_start(text_renderer, True)
  70.         col1.set_attributes(text_renderer, text=3)
  71.         self.treeview.append_column(col1)
  72.  
  73.         toggle_renderer = gtk.CellRendererToggle()
  74.         toggle_renderer.set_property("activatable", True)
  75.         toggle_renderer.connect("toggled", self.on_renderer_toggled)
  76.         col2 = gtk.TreeViewColumn(_("Enabled"))
  77.         col2.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
  78.         col2.set_expand(False)
  79.         col2.pack_start(toggle_renderer, True)
  80.         col2.set_attributes(toggle_renderer, active=4)
  81.         self.treeview.append_column(col2)
  82.  
  83.         pixbuf_renderer = gtk.CellRendererPixbuf()
  84.         text_renderer = gtk.CellRendererText()
  85.         col3 = gtk.TreeViewColumn(_("Status"))
  86.         col3.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
  87.         col3.set_expand(False)
  88.         col3.pack_start(pixbuf_renderer, False)
  89.         col3.pack_end(text_renderer, True)
  90.         col3.set_attributes(pixbuf_renderer, pixbuf=5)
  91.         col3.set_attributes(text_renderer, text=6)
  92.         self.treeview.append_column(col3)
  93.  
  94.         self.button_close = self.xml.get_widget("button_close")
  95.         self.button_close.connect("clicked", self.on_button_close_clicked)
  96.  
  97.         self.handlers = handlers
  98.         self.reset_model()
  99.  
  100.         # to remove the selection outline around the first item of the tree
  101.         self.treeview.grab_focus()
  102.  
  103.         self.dialog.show()
  104.  
  105.     def reset_model(self):
  106.         self.model = gtk.ListStore(gobject.TYPE_PYOBJECT,
  107.                                    gobject.TYPE_PYOBJECT,
  108.                                    gobject.TYPE_PYOBJECT,
  109.                                    str, bool, gtk.gdk.Pixbuf, str)
  110.  
  111.         theme = gtk.icon_theme_get_default()
  112.         handlers = sorted(self.handlers.values(), key=lambda x: x.description)
  113.         for handler in handlers:
  114.             is_enabled = handler.is_enabled()
  115.             is_loaded = handler.is_loaded()
  116.             if (is_enabled != is_loaded) and handler.is_changed():
  117.                 status, icon = _("Needs computer restart"), "reboot-notifier"
  118.             elif is_loaded:
  119.                 status, icon = _("In use"), gtk.STOCK_YES
  120.             else:
  121.                 status, icon = _("Not in use"), gtk.STOCK_NO
  122.             try:
  123.                 pixbuf = theme.load_icon(icon, 16, gtk.ICON_LOOKUP_USE_BUILTIN)
  124.             except:
  125.                 # do not fail if icon is not found, just create a 1px pixbuf
  126.                 pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, 1, 1)
  127.             self.model.append([ handler, is_enabled, is_loaded,
  128.                                 handler.description, is_enabled, pixbuf,
  129.                                 status ])
  130.  
  131.         self.treeview.set_model(self.model)
  132.  
  133.     def on_dialog_delete_event(self, *args):
  134.        gtk.main_quit()
  135.  
  136.     def on_renderer_toggled(self, widget, path, *args):
  137.         self.action(path)
  138.  
  139.     def action(self, path):
  140.         handler = self.model[path][0]
  141.         is_enabled = self.model[path][1]
  142.         is_loaded = self.model[path][2]
  143.  
  144.         ch = handler.can_change()
  145.  
  146.         if not ch:
  147.             dlg = ConfirmDialog(self.xml, handler, is_enabled, self.dialog)
  148.             if dlg.run() != gtk.RESPONSE_OK:
  149.                 return
  150.  
  151.             self.treeview.set_sensitive(False)
  152.             if is_enabled:
  153.                 handler.disable()
  154.  
  155.                 if handler.is_loaded():
  156.                     notify_reboot_required()
  157.             else:
  158.                 handler.enable()
  159.             self.treeview.set_sensitive(True)
  160.         else:
  161.             md = gtk.MessageDialog(self.dialog, type=gtk.MESSAGE_ERROR,
  162.                         buttons=gtk.BUTTONS_CLOSE, message_format=ch)
  163.             md.run()
  164.             md.hide()
  165.             return
  166.  
  167.         self.reset_model()
  168.         self.treeview.grab_focus()
  169.  
  170.     def on_button_close_clicked(self, *args):
  171.         gtk.main_quit()
  172.  
  173.  
  174. class ConfirmDialog(object):
  175.     def __init__(self, xml, handler, is_enabled, parent=None):
  176.         self.xml = xml
  177.         self.handler = handler
  178.         self.is_enabled = is_enabled
  179.  
  180.         self.dialog = self.xml.get_widget("dialog_confirm")
  181.         self.dialog.set_title("")
  182.         if parent is not None:
  183.             self.dialog.set_transient_for(parent)
  184.         self.xml.get_widget("button_cancel").grab_focus()
  185.  
  186.         if self.is_enabled:
  187.             frob = _("Disable the driver?")
  188.             self.xml.get_widget("label_ok").set_label(_("_Disable Driver"))
  189.         else:
  190.             frob = _("Enable the driver?")
  191.             self.xml.get_widget("label_ok").set_label(_("_Enable Driver"))
  192.  
  193.         label = self.xml.get_widget("label_text")
  194.         label.set_label("<span weight=\"bold\" size=\"larger\">"
  195.                         "%s"
  196.                         "</span>\n\n"
  197.                         "<span weight=\"bold\">%s</span>\n\n"
  198.                         "%s" % (frob, handler.description, handler.rationale))
  199.  
  200.     def run(self):
  201.         ret = self.dialog.run()
  202.         self.dialog.hide()
  203.         return ret
  204.  
  205.  
  206. class Notification(object):
  207.     def __init__(self):
  208.         self.trayicon = gtk.status_icon_new_from_icon_name("restricted-manager")
  209.         self.trayicon.connect("activate", self.open_manager)
  210.         self.trayicon.set_tooltip(_("New Restricted Drivers in use"))
  211.  
  212.         gobject.timeout_add (500, self.show_notify)
  213.  
  214.     def show_notify(self):
  215.         pynotify.init("restricted-manager")
  216.  
  217.         notify = pynotify.Notification(_("New restricted drivers in use"),
  218.            "<span weight=\"bold\">%s</span>\n\n%s" % (
  219.                 _("In order for this computer to function properly, Ubuntu is "
  220.                   "using driver software that cannot be supported"),
  221.                 _("Click on this icon to open the Restricted Drivers control "
  222.                   "panel.")), "restricted-manager")
  223.         notify.set_urgency(pynotify.URGENCY_NORMAL)
  224.         notify.attach_to_status_icon(self.trayicon)
  225.         notify.show()
  226.  
  227.     def open_manager(self, *args):
  228.         runme_as_root()
  229.  
  230. def runme_as_root(extra_argv = []):
  231.     """Execute myself through gksu."""
  232.  
  233.     argv = ["gksu", "-D", _("Restricted Drivers manager"),
  234.               "--", sys.argv[0]] + extra_argv
  235.     os.execvp("gksu", argv)
  236.  
  237. def gtk_idle():
  238.     while gtk.events_pending():
  239.         gtk.main_iteration(False)
  240.  
  241. def main(args, opts):
  242.     try:
  243.         xml = gtk.glade.XML("/usr/share/restricted-manager/manager.glade")
  244.     except RuntimeError:
  245.         glade_filename = os.path.join(os.path.dirname(RestrictedManager.__file__),
  246.                                       "manager.glade")
  247.         xml = gtk.glade.XML(glade_filename)
  248.  
  249.     RestrictedManager.core.package_install_idle_function = gtk_idle
  250.  
  251.     # set the title label here instead of the glade file, so that it can be
  252.     # translated more easily
  253.     xml.get_widget("label_heading").set_label('<span weight="bold">%s</span>\n\n%s' % (
  254.         _("In order for this computer to function properly, Ubuntu may be using driver software that cannot be supported."),
  255.         _("Because the software is proprietary, it cannot easily be changed to fix any future problems.")
  256.     ))
  257.  
  258.     if not am_admin():
  259.         print >>sys.stderr, _("Must be run as member of admin group")
  260.         return 1
  261.  
  262.     if opts.update:
  263.         load_restricted_list(force=True)
  264.     elif opts.list:
  265.         handlers = get_handlers()
  266.         for handler in handlers.values():
  267.             print handler.name
  268.     elif opts.check:
  269.         handlers = get_handlers()
  270.         used = load_used_list()
  271.         new = []
  272.  
  273.         for handler in handlers.values():
  274.             if handler.name in used:
  275.                 continue
  276.             elif handler.is_loaded():
  277.                 new.append(handler.name)
  278.  
  279.         if new:
  280.             used.extend(new)
  281.             save_used_list(used)
  282.  
  283.             Notification()
  284.             gtk.main()
  285.     elif opts.check_composite:
  286.         handlers = get_handlers()
  287.         try:
  288.             handler = handlers["nvidia"]
  289.             if handler.is_enabled():
  290.                 print "nvidia restricted driver is already enabled"
  291.                 return 1
  292.         except KeyError:
  293.             print "nvidia hardware not available"
  294.             return 1
  295.  
  296.         runme_as_root(["--enable", "nvidia"])
  297.  
  298.     elif os.getuid() > 0:
  299.         print >>sys.stderr, _("Must be run as root")
  300.         return 1
  301.     elif opts.enable:
  302.         handlers = get_handlers()
  303.         try:
  304.             handler = handlers[opts.enable]
  305.         except KeyError:
  306.             print >>sys.stderr, _("Unknown module: %s") % opts.enable
  307.             return 1
  308.  
  309.         if handler.is_enabled():
  310.             print >>sys.stderr, _("%s is already enabled") % opts.enable
  311.             return 1
  312.  
  313.         ch = handler.can_change()
  314.         if ch:
  315.             md = gtk.MessageDialog(type=gtk.MESSAGE_ERROR,
  316.                         buttons=gtk.BUTTONS_CLOSE, message_format=ch)
  317.             md.run()
  318.             md.hide()
  319.             return
  320.  
  321.         if ConfirmDialog(xml, handler, False).run() != gtk.RESPONSE_OK:
  322.             return
  323.  
  324.         handler.enable()
  325.     elif opts.disable:
  326.         handlers = get_handlers()
  327.         try:
  328.             handler = handlers[opts.disable]
  329.         except KeyError:
  330.             print >>sys.stderr, "Unknown module: %s" % opts.disable
  331.             return 1
  332.  
  333.         if not handler.is_enabled():
  334.             print >>sys.stderr, "%s is already disabled" % opts.disable
  335.             return 1
  336.  
  337.         ch = handler.can_change()
  338.         if ch:
  339.             md = gtk.MessageDialog(type=gtk.MESSAGE_ERROR,
  340.                         buttons=gtk.BUTTONS_CLOSE, message_format=ch)
  341.             md.run()
  342.             md.hide()
  343.             return
  344.  
  345.         if ConfirmDialog(xml, handler, True).run() != gtk.RESPONSE_OK:
  346.             return
  347.  
  348.         handler.disable()
  349.     else:
  350.         # check whether we have restricted modules installed
  351.         lrm = "linux-restricted-modules-" + os.uname()[2]
  352.         if not DefaultHandler.package_installed(lrm):
  353.             md = gtk.MessageDialog(type=gtk.MESSAGE_ERROR,
  354.                         buttons=gtk.BUTTONS_CLOSE, message_format=_(
  355.                         "You need to install the package\n\n  %s\n\nfor this program to work.") % lrm)
  356.             md.run()
  357.             md.hide()
  358.             return 0
  359.  
  360.         handlers = get_handlers()
  361.  
  362.         if not handlers:
  363.             md = gtk.MessageDialog(type=gtk.MESSAGE_INFO,
  364.                         buttons=gtk.BUTTONS_CLOSE, message_format=_(
  365.                         "Your hardware does not need any restricted drivers."))
  366.             md.run()
  367.             md.hide()
  368.             return 0
  369.  
  370.         ManagerWindow(xml, handlers)
  371.         RestrictedManager.core.package_install_xid = \
  372.             xml.get_widget("dialog_manager").window.xid
  373.  
  374.         gtk.main()
  375.  
  376. def get_opt_args():
  377.     parser = OptionParser()
  378.     parser.add_option ("-u", "--update", action="store_true",
  379.                        dest="update", default=False,
  380.                        help=_("Update restricted modules list"))
  381.     parser.add_option ("-c", "--check", action="store_true",
  382.                        dest="check", default=False,
  383.                        help=_("Check for newly used restricted modules"))
  384.     parser.add_option ("-l", "--list", action="store_true",
  385.                        dest="list", default=False,
  386.                        help=_("List available restricted modules"))
  387.     parser.add_option ("-C", "--check-composite", action="store_true",
  388.                        dest="check_composite", default=False,
  389.                        help=_("Check if there is a graphics driver available that supports composite and offer to enable it"))
  390.     parser.add_option ("-e", "--enable", type="string",
  391.                        dest="enable", default="", metavar="MODULE",
  392.                        help=_("Enable the named module"))
  393.     parser.add_option ("-d", "--disable", type="string",
  394.                        dest="disable", default="", metavar="MODULE",
  395.                        help=_("Disable the named module"))
  396.     return parser.parse_args()
  397.  
  398. if __name__ == "__main__":
  399.     gettext.textdomain("restricted-manager")
  400.     gtk.glade.textdomain("restricted-manager")
  401.     #gettext.bindtextdomain("restricted-manager", "po/mo")
  402.     (opts, args) = get_opt_args()
  403.  
  404.     sys.exit(main(args, opts))
  405.